﻿#if NETFX ||WINDOWS_PHONE
using System.Security.Cryptography;

#elif NETFX_CORE
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.DataProtection;
#endif

using LibNiconico.NiconicoApi.Videos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;

using System.Text;
using System.Threading.Tasks;


namespace NicoView.Model.Service
{

    /// <summary>
    /// 安全なニコニコ認証情報
    /// </summary>
    public sealed class NicoSafeUserAuth
    {


        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="mail"></param>
        /// <param name="userSession"></param>
        public NicoSafeUserAuth(Guid identificationKey, Cookie userSession)
        {
            this.IdentificationKey = identificationKey;
            if (userSession != null){

                this.UserSession = ToSafeCookie(userSession);

            }else
            {
                UserSession = userSession;
            }
            
            
        }

        internal static Cookie ToSafeCookie(Cookie cookie)
        {

            if (cookie != null)
            {
                var newCookie = new Cookie(cookie.Name, encrypto(cookie.Value), cookie.Path, cookie.Domain);
                newCookie.HttpOnly = cookie.HttpOnly;
                newCookie.Port = cookie.Port;
                newCookie.Expires = cookie.Expires;

                return newCookie;
            }
            else
            {
                return null;
            }

        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public NicoSafeUserAuth() : this(Guid.NewGuid(), (Cookie)null) { }



        /// <summary>
        /// 識別キー
        /// </summary>
        public Guid IdentificationKey { get; set; }


        private string mail { get; set; }

        /// <summary>
        /// 認証メールアドレス
        /// </summary>
        internal string Mail
        {

            get;
            set;

        }


        /// <summary>
        /// ユーザセッション
        /// </summary>
        public Cookie UserSession { get; set; }





        /// <summary>
        /// 認証情報が有効か判定
        /// </summary>
        /// <returns></returns>
        public bool IsEnableAuth()
        {
            return UserSession != null && UserSession.Expires > DateTime.Now;
        }


        internal Cookie GetUserSession()
        {
            return new Cookie(UserSession.Name, decrypto(UserSession.Value), UserSession.Path, UserSession.Domain);
        }




#if NETFX ||WINDOWS_PHONE
       

        private static string encrypto(string target)
        {
            try
            {
                var provider = _generateCryptoProvider();
                var encryptor = provider.CreateEncryptor();
                var targetBytes = Encoding.UTF8.GetBytes(target);
                var encBytes = encryptor.TransformFinalBlock(targetBytes, 0, targetBytes.Length);
                return Convert.ToBase64String(encBytes);
            }
            catch 
            {
                return "";
            }
        }

        private static string decrypto(string target)
        {
            try
            {
                var provider = _generateCryptoProvider();
                var decryptor = provider.CreateDecryptor();
                var targetBytes = Convert.FromBase64String(target);
                var decBytes = decryptor.TransformFinalBlock(targetBytes, 0, targetBytes.Length);
                return Encoding.UTF8.GetString(decBytes, 0, decBytes.Count());
            }
            catch 
            {
                return "";
            }
        }

#if NETFX
        private static AesCryptoServiceProvider _generateCryptoProvider()
        {
            var provider = new AesCryptoServiceProvider();
            provider.Key = new byte[] { 12, 47, 88, 54, 69, 87, 114, 24, 63, 54, 77, 87, 74, 52, 66,22 };
            provider.IV = new byte[] { 13, 20, 96, 1, 4, 112, 55, 21, 36, 52, 44, 3, 79, 51, 63,55 };
            return provider;
        }
#elif WINDOWS_PHONE
        private static AesManaged _generateCryptoProvider()
        {
            var provider = new AesManaged();
            provider.Key = new byte[] { 12, 47, 88, 54, 69, 87, 114, 24, 63, 54, 77, 87, 74, 52, 66, 22 };
            provider.IV = new byte[] { 13, 20, 96, 1, 4, 112, 55, 21, 36, 52, 44, 3, 79, 51, 63, 55 };
            return provider;
        }

#endif


#elif NETFX_CORE 

        private const string protectionDescriptor = "NICOVIEW_PROTECTION";

        private static string encrypto(string target)
        {
            var dataProtectionProvider = new DataProtectionProvider(protectionDescriptor);
            var buffer =CryptographicBuffer.ConvertStringToBinary(target,BinaryStringEncoding.Utf8);
            var encBytes = dataProtectionProvider.ProtectAsync(buffer).GetResults();

            return CryptographicBuffer.EncodeToBase64String(encBytes);

        }

        private static string decrypto(string target)
        {
            
            var dataProtectionProvider = new DataProtectionProvider(protectionDescriptor);
            var base64 = CryptographicBuffer.DecodeFromBase64String(target);
            var decBytes = dataProtectionProvider.UnprotectAsync(base64).GetResults();
            return CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8,decBytes);
            
        }

#endif
    }

}
